//-------------------------------------------------------------------
//	Copyright (c) 2012-2014 Zhirnov Andrey
//	This file is part of the "UXGEN-ES" project.
//	See copyright notice in "Engine.h".
//-------------------------------------------------------------------

#pragma once

#include "UI/Animation/Frame/IFrameAnimation.h"
#include "UI/Widgets/Frame.h"

namespace Engine
{
namespace UI
{

	class FrameFadeAnimation;
	SHARED_POINTER( FrameFadeAnimation );


	//
	// Frame Fade Animation
	//

	class FrameFadeAnimation : public IFrameAnimation
	{
	// types
	private:
		static const Graphics::EPixelFormat::type		PIXEL_FORMAT = Graphics::EPixelFormat::RGBA8;


	// variables
	private:
		Graphics::Texture			_rt;
		Graphics::FrameBuffer		_fb;
		Graphics::BatchMaterial		_mtr;

		OnAnimFinishedCallback_t	_cb;
		float						_duration;
		bool						_started;


	// methods
	private:
		FrameFadeAnimation (const EngineSubSystemsRef ess) :
			IFrameAnimation(ess), _rt(ess), _fb(ess),
			_started(false), _duration(0.5f)
		{}


	public:
		void SetDuration (float duration) override
		{
			_duration = duration;
		}


		void Start (const FramePtr &animatedFrame, const ScreenPtr &screen, OnAnimFinished_t func) override
		{
			typedef WidgetMsg	WM;

			Stop();

			_started = true;
			_cb = OnAnimFinishedCallback_t( func, screen );

			const ivec2 &	size = ESS()->GetGraphicsEngine()->GetViewport()->Size();

			if ( Any( size != _rt.Dimension().xy().To<ivec2>() ) )
			{
				_rt.Destroy();
				_rt.Alloc( uvec3( size.To<uvec2>(), 0 ), PIXEL_FORMAT, 0 );
			}

			_mtr.SetTexture( 0, &_rt );

			_fb.Create();
			_fb.Bind();
			_fb.Attach( _rt, Graphics::gl_fbo_attach::COLOR );
			
			if ( not _fb.CheckStatus() )
			{
				_fb.Unbind();
				Stop();
				return;
			}
			
			ESS()->GetGraphicsEngine()->GetViewport()->Mode2D();

			animatedFrame->ReArrange();
			animatedFrame->ProcessMessage( WM( WM::DRAW, WM::Draw( screen.ptr() ) ) );

			_fb.Unbind();
		}


		void Stop () override
		{
			if ( _started )
			{
				_fb.Destroy();
				_cb.Call();
				_started = false;
			}
		}


		void Draw (uint firstFrame, const frame_stack_t &frames, float timeDelta) override
		{
			typedef WidgetMsg	WM;

			for (; firstFrame < frames.Count(); ++firstFrame)
			{
				Ptr< Frame >	frame = frames[ firstFrame ].ptr();

				frame->ProcessMessage( WM( WM::DRAW, WM::Draw( _cb.GetParameter().ToPtr<Screen>() ) ) );
			}

			ESS()->GetGraphicsEngine()->GetRender2D().DrawFullscreenQuad( _mtr );
		}


		static FrameFadeAnimationPtr New (const EngineSubSystemsRef ess)
		{
			return BaseObject::_New( new FrameFadeAnimation( ess ) );
		}
	};


}	// UI
}	// Engine
